package com.qclix.inv;

import com.qclix.inv.dao.ClientDAO;
import com.qclix.inv.dao.DAOException;
import com.qclix.inv.dao.InvoiceDAO;
import com.qclix.inv.pdf.PDFCreationException;
import com.qclix.inv.pdf.PDFCreator;
import org.apache.log4j.Logger;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.io.*;
import java.util.*;


/**
 * Provides different services for invoice manipulation
 */
public class InvoiceServiceDefaultImpl extends HibernateDaoSupport implements InvoiceService {
    private static final Logger LOGGER = Logger.getLogger(InvoiceServiceDefaultImpl.class);

    private static final int LAST_INVOICE_TO_RETURN = 9; // TODO inject value from Spring

    private ClientDAO clientDAO;
    private InvoiceDAO invoiceDAO;
    private PDFCreator pdfCreator;

    public void setClientDAO(ClientDAO clientDAO) {
        this.clientDAO = clientDAO;
    }

    public void setInvoiceDAO(InvoiceDAO invoiceDAO) {
        this.invoiceDAO = invoiceDAO;
    }

    public void setPdfCreator(PDFCreator pdfCreator) {
        this.pdfCreator = pdfCreator;
    }

    @SuppressWarnings("unchecked")
    public List<Client> getClients() throws InvoiceServiceException {
        try {
            return clientDAO.getClients();
        } catch (DAOException e) {
            throw new InvoiceServiceException(e);
        }
    }

    @Transactional(propagation = Propagation.REQUIRED)
    public Client addClient(Client client) throws InvoiceServiceException {
        try {
            clientDAO.addClient(client);
        } catch (DAOException e) {
            throw new InvoiceServiceException(e);
        }
        return client;
    }

    public boolean hasAtLeastOneClient() throws InvoiceServiceException {
        try {
            return clientDAO.getClientCount() > 0;
        } catch (DAOException e) {
            throw new InvoiceServiceException(e);
        }
    }

    @Transactional(propagation = Propagation.SUPPORTS, isolation = Isolation.SERIALIZABLE)
    public void addInvoice(Invoice invoice) throws InvoiceServiceException {
        Calendar issueDate = Calendar.getInstance();
        issueDate.setTime(invoice.getIssueDate());
        int year = issueDate.get(Calendar.YEAR);
        long amountOfInvoicesThisYear = 0;//getAmountOfInvoicesInYear(year);
        try {
            amountOfInvoicesThisYear = invoiceDAO.getAmountOfInvoicesOnYear(year);
            StringBuilder buffer = new StringBuilder();
            buffer.append(year);
            if (amountOfInvoicesThisYear < 9) {
                buffer.append('0');
            }
            if (amountOfInvoicesThisYear < 99) {
                buffer.append('0');
            }
            if (amountOfInvoicesThisYear < 999) {
                buffer.append('0');
            }
            buffer.append(amountOfInvoicesThisYear + 1);
            invoice.setNumber(buffer.toString());
            invoiceDAO.add(invoice);
        } catch (DAOException e) {
            throw new InvoiceServiceException(e);
        }
    }

    public Client getLastInvoicedClient() throws InvoiceServiceException {
        try {
            return invoiceDAO.getLastInvoice().getClient();
        } catch (DAOException e) {
            throw new InvoiceServiceException(e);
        }
    }

    @SuppressWarnings("unchecked")
    public List<Invoice> getLastInvoices() throws InvoiceServiceException {
        try {
            return invoiceDAO.getLastInvoices(LAST_INVOICE_TO_RETURN);
        } catch (DAOException e) {
            throw new InvoiceServiceException(e);
        }
    }

    public byte[] getPDF(Invoice invoice) throws InvoiceServiceException {
        try {
            return pdfCreator.getPDF(invoice);
        } catch (PDFCreationException e) {
            throw new InvoiceServiceException(e);
        }
    }

    public void writePDF(Invoice invoice, File outputFile) throws InvoiceServiceException {
        try {
            pdfCreator.writePDF(invoice, outputFile);
        } catch (PDFCreationException e) {
            throw new InvoiceServiceException(e);
        }
    }
}
